#include "clientManager.h"

void * startClientThread(void *arg){
	Client * newClient = (Client*)arg;
	newClient->startRequest();
	return NULL;
}

ClientManager::ClientManager(ClientConfigType *clientConfigInfo){
	_zipfParameter = clientConfigInfo->zipfParameter;
	_poissonParameter = clientConfigInfo->poissonLambda;
	_resourceNumber = clientConfigInfo->resourceNumber;
	_requestListFile = clientConfigInfo->requestListFile;
	_clientConfig = clientConfigInfo;	
}

ClientManager::~ClientManager(){
}

int
ClientManager::getZipfDistribution(vector<double> &distribution){
	double denominator = 0.0;
	double u;
	for(unsigned int i = 0;i<_clientConfig->resourceNumber;i++){
		denominator += pow(i+1,0 - _zipfParameter);	
	}
	for(unsigned int i = 0;i< _clientConfig->resourceNumber;i++){
		u = pow(i+1,0 - _zipfParameter);
		u = u/ denominator;
		distribution.push_back(u);
	}
	return 0;
}


int
ClientManager::startAllClients(){
	size_t j;
	vector<double> distribution;
	getZipfDistribution(distribution);
	j= _requestListFile.find('.',0);
	string myConfigFile = _requestListFile.substr(0,j) +"_" + numToString(1000 * _zipfParameter) + "_"
		+ numToString(1000* _poissonParameter) + "_" + numToString(_resourceNumber) + _requestListFile.substr(j);
	_requestListFile = myConfigFile;
	fstream ifs(_requestListFile.c_str());
	pthread_t tid;
	unsigned int timeInterval;
	unsigned int requestFileId;
	if(!ifs){
		double temp;
		for(int i=0;;i++){
			requestFileId = getRequestFileId(distribution);
			if(i ==0){
				timeInterval = 0;		
			}else{
				temp = Randomf(0,1);
				temp = 1 - temp;
				temp = 0 - log(temp)/_poissonParameter;
				timeInterval =(int) 1000000 * temp;
			}
			ifs << requestFileId <<" "<<  timeInterval <<endl;
			usleep(timeInterval);
			cout<<"client "<<i<<" will request file "<<requestFileId<<endl;
			Client *newClient = new Client(i,_clientConfig->serverIpAddress,_clientConfig->serverPort,_clientConfig->clientBandwidth,requestFileId);
			pthread_create(&tid,NULL,&startClientThread,newClient);
			pthread_detach(tid);
		}
	}else{
		unsigned int a,b;
		unsigned int i =0;
		while(ifs.eof()){
			ifs >> a >> b;
			mysleep(b);
			Client *newClient = new Client(i,_clientConfig->serverIpAddress,_clientConfig->serverPort,_clientConfig->clientBandwidth,a);
			pthread_create(&tid,NULL,&startClientThread,newClient);
			pthread_detach(tid);
			i++;
		}

	}
	return 0;
}


unsigned int
ClientManager::getRequestFileId(const vector<double> &distribution){
	double sum =0.0;
	double temp;
	temp = Randomf(0,1);
	for(int i = _resourceNumber-1;i>=0;i--){
		sum += distribution.at(i);
		if(sum >= temp)
			return i+1;
	}
	return 0;
}

